package com.corgi.mybatis.util;

import lombok.extern.slf4j.Slf4j;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import java.io.IOException;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

/**
 * @title: RsaUtil
 * @description:
 * @author: dengmiao
 * @create: 2019-10-28 09:10
 **/
@Slf4j
public class RsaUtil {

    private static final String PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArkDK6QM+edJrQJeuy7VdnCh4CSt7yolgFAPKxLq/5K9lg2BXV1/H1UmhwdD5FBjKDjIxcgus5l0vF/3XYUFcH4MBnR3s/uK26qbEOfSGHaYqxuDKGgOUEpY5pSt5FVdf/awuK2lxog4EMsW30aE0oXj/ULG9grqKUrVbOzkoFX5x4NKcPECII69ydgmmoeMeURueu7vP/kQQcoc1tR12oRpGaD3gfn1L1QUsftPq65JUTgl4W8PObJnMJQ/pnI5hNlWJ3c89+Gka20bvjBGqwaALj2n2HDyLszKq1gtv8B3N7PT7imM/c7+vPpifs3ZtR+wzmm0sDzHa0I3rZEGmBQIDAQAB";

    private final static String PRIVATE_KEY = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCuQMrpAz550mtAl67LtV2cKHgJK3vKiWAUA8rEur/kr2WDYFdXX8fVSaHB0PkUGMoOMjFyC6zmXS8X/ddhQVwfgwGdHez+4rbqpsQ59IYdpirG4MoaA5QSljmlK3kVV1/9rC4raXGiDgQyxbfRoTSheP9Qsb2CuopStVs7OSgVfnHg0pw8QIgjr3J2Caah4x5RG567u8/+RBByhzW1HXahGkZoPeB+fUvVBSx+0+rrklROCXhbw85smcwlD+mcjmE2VYndzz34aRrbRu+MEarBoAuPafYcPIuzMqrWC2/wHc3s9PuKYz9zv68+mJ+zdm1H7DOabSwPMdrQjetkQaYFAgMBAAECggEBAIImlugPqjxndABcywwQPQkEGRQQTHfsv7xzUKI8MlPmxdWowdPbEHE4e/89zKy8Dz8nMlNScSPm+ePbj2Fu5hYLTctCrN98Cs+dG/eFsh63HEBLaeigP5raZdf+boQILQRV9G4sZdl6ypv5neCPnbX1oA1vlHLuTZ6VIr1LZasW9YBmkKcUfxbz9+90g7+I0eoGHklh92ojm6eeyLO1H4J+ImDAVOx0SyDiMYZvK0ESHdY/PW9a4MosOrhk371VNkSUnsT5tfpjyYk9p5zPeaiQh4Hse/gkviYOQpCF9KCbYFvtZ3ZAvLjhySI3x1mMsQ9IvLyUGzOwR7DALbsJEQkCgYEA9Ub+WBIu0/+MTFd4Mt9rgPvmffp5pEHB3dNy97/GgHYJ1Fa7LksezDHPZg7jha1DOeV+y00W1zBIH7s/PMf1oOjXYeeZfLQEBIRd9t8BOjj8C5WCBIieYVlbTihflgpp9w/BLbRrAC4ZXF6Q1wI04tim5JLtqfK2p8oYL9R4uK8CgYEAtd7vjMxK2Af2w5JSorvSiGNhVC1bkA3pJIlKENKH6AoLg7g70ryNM/9k/5M3QDRazYHRKk79i9HoXGzUYzmMW8wHbpZi95AM/xe/mVglpjkStFm8xvife1ioPPCRigOTQ02M/HoqD7bKAxFlK4TKtJj+z3+SCz0GIK8fWrWaUYsCgYAScYQumy9qQY0LMIiZSrOKv2ZVksAS2d76DyxV9NW4UyfqD5uDn6JxOE2gHv58zsp/UAJ4xxMwmzDRMgNPTrnpn5iShBfGiMLElC98oMg22JIbTOK59Iv0RgPXnLGTVrUhHs4n4akqGk1N5M5/XGsdo6zpAyNb5CRX+ZpX/mIVgQKBgQCPrtESK1P12FTbrX4bkseBeQIrvqnX5SWL9+rL34f/ifAO4D5i/xOPQPZJ88RytOoH8ceN5VnqXKt2WYRx38VDwK0ecTE+5E9gOSLlwv37lJtyYHMDvuhASoqfmm9g2fI9+caosNsKDx8JzXRgLUj35Odqhx6aQlvU9oWO5GpGgQKBgQDHUl96r4UqYq6ckaw2cOJdqiMqaSSe41M+vTvaafHYN28CfnnHuFkb4gox2rkya/EK1dUOaDGk5kqruhG1NYkpC6ern2N9qA4n5jFomBqr6ru7nVAV6Td+t53trerkeNakUBTVXN9u6MMxw2zKYXwjd6dpXwS0QswivxHQYFBZRA==";

    /**
     * 生成秘钥对
     * @return
     * @throws Exception
     */
    public static KeyPair getKeyPair() throws Exception {
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");
        keyPairGenerator.initialize(2048);
        KeyPair keyPair = keyPairGenerator.generateKeyPair();
        return keyPair;
    }

    /**
     * 获取公钥(Base64编码)
     * @param keyPair
     * @return
     */
    public static String getPublicKey(KeyPair keyPair) {
        PublicKey publicKey = keyPair.getPublic();
        byte[] bytes = publicKey.getEncoded();
        return byte2Base64(bytes);
    }

    /**
     * 获取私钥(Base64编码)
     * @param keyPair
     * @return
     */
    public static String getPrivateKey(KeyPair keyPair) {
        PrivateKey privateKey = keyPair.getPrivate();
        byte[] bytes = privateKey.getEncoded();
        return byte2Base64(bytes);
    }

    /**
     * 将Base64编码后的公钥转换成PublicKey对象
     * @param pubStr
     * @return
     * @throws Exception
     */
    public static PublicKey string2PublicKey(String pubStr) throws Exception {
        byte[] keyBytes = base642Byte(pubStr);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PublicKey publicKey = keyFactory.generatePublic(keySpec);
        return publicKey;
    }

    /**
     * 将Base64编码后的私钥转换成PrivateKey对象
     * @param priStr
     * @return
     * @throws Exception
     */
    public static PrivateKey string2PrivateKey(String priStr) throws Exception {
        byte[] keyBytes = base642Byte(priStr);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
        return privateKey;
    }

    /**
     * 公钥加密
     * @param content
     * @param publicKey
     * @return
     */
    public static String publicEncrypt(String content, String publicKey) {
        try {
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, string2PublicKey(publicKey));
            byte[] bytes = cipher.doFinal(content.getBytes());
            return byte2Base64(bytes);
        } catch (Exception e) {
            log.error("公钥加密失败{}", e);
        }
        return null;
    }

    public static String publicEncrypt(String content) {
        return publicEncrypt(content, PUBLIC_KEY);
    }

    /**
     * 私钥解密
     * @param content
     * @param privateKey
     * @return
     */
    public static String privateDecrypt(String content, String privateKey) {
        try {
            log.info("content: {}", content);
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, string2PrivateKey(privateKey));
            byte[] bytes = cipher.doFinal(base642Byte(content));
            return new String(bytes);
        } catch (Exception e) {
            log.error("私钥解密失败: {}", e.getMessage());
            e.printStackTrace();
        }
        return null;
    }

    public static String privateDecrypt(String content) {
        return privateDecrypt(content, PRIVATE_KEY);
    }

    /**
     * 字节数组转Base64编码
     * @param bytes
     * @return
     */
    public static String byte2Base64(byte[] bytes) {
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(bytes);
    }

    /**
     * Base64编码转字节数组
     * @param base64Key
     * @return
     * @throws IOException
     */
    public static byte[] base642Byte(String base64Key) throws IOException {
        BASE64Decoder decoder = new BASE64Decoder();
        return decoder.decodeBuffer(base64Key);
    }

    public static void main(String[] args) {
        try {
            String publicKeyStr = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArkDK6QM+edJrQJeuy7VdnCh4CSt7yolgFAPKxLq/5K9lg2BXV1/H1UmhwdD5FBjKDjIxcgus5l0vF/3XYUFcH4MBnR3s/uK26qbEOfSGHaYqxuDKGgOUEpY5pSt5FVdf/awuK2lxog4EMsW30aE0oXj/ULG9grqKUrVbOzkoFX5x4NKcPECII69ydgmmoeMeURueu7vP/kQQcoc1tR12oRpGaD3gfn1L1QUsftPq65JUTgl4W8PObJnMJQ/pnI5hNlWJ3c89+Gka20bvjBGqwaALj2n2HDyLszKq1gtv8B3N7PT7imM/c7+vPpifs3ZtR+wzmm0sDzHa0I3rZEGmBQIDAQAB";
            //=================客户端=================
            String message = "{\"userPhone\":\"13500035111\",\"loginToken\":\"NN8dR1712810NWC78ZSFc7aOD3ymS41Q\",\"merchantNo\":\"shang001\"}";
            // 公钥加密
            String byte2Base64 = RsaUtil.publicEncrypt(message, publicKeyStr);
            System.out.println("公钥加密并Base64编码的结果：" + byte2Base64);
            //===================服务端================
            String privateKeyStr = "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCuQMrpAz550mtAl67LtV2cKHgJK3vKiWAUA8rEur/kr2WDYFdXX8fVSaHB0PkUGMoOMjFyC6zmXS8X/ddhQVwfgwGdHez+4rbqpsQ59IYdpirG4MoaA5QSljmlK3kVV1/9rC4raXGiDgQyxbfRoTSheP9Qsb2CuopStVs7OSgVfnHg0pw8QIgjr3J2Caah4x5RG567u8/+RBByhzW1HXahGkZoPeB+fUvVBSx+0+rrklROCXhbw85smcwlD+mcjmE2VYndzz34aRrbRu+MEarBoAuPafYcPIuzMqrWC2/wHc3s9PuKYz9zv68+mJ+zdm1H7DOabSwPMdrQjetkQaYFAgMBAAECggEBAIImlugPqjxndABcywwQPQkEGRQQTHfsv7xzUKI8MlPmxdWowdPbEHE4e/89zKy8Dz8nMlNScSPm+ePbj2Fu5hYLTctCrN98Cs+dG/eFsh63HEBLaeigP5raZdf+boQILQRV9G4sZdl6ypv5neCPnbX1oA1vlHLuTZ6VIr1LZasW9YBmkKcUfxbz9+90g7+I0eoGHklh92ojm6eeyLO1H4J+ImDAVOx0SyDiMYZvK0ESHdY/PW9a4MosOrhk371VNkSUnsT5tfpjyYk9p5zPeaiQh4Hse/gkviYOQpCF9KCbYFvtZ3ZAvLjhySI3x1mMsQ9IvLyUGzOwR7DALbsJEQkCgYEA9Ub+WBIu0/+MTFd4Mt9rgPvmffp5pEHB3dNy97/GgHYJ1Fa7LksezDHPZg7jha1DOeV+y00W1zBIH7s/PMf1oOjXYeeZfLQEBIRd9t8BOjj8C5WCBIieYVlbTihflgpp9w/BLbRrAC4ZXF6Q1wI04tim5JLtqfK2p8oYL9R4uK8CgYEAtd7vjMxK2Af2w5JSorvSiGNhVC1bkA3pJIlKENKH6AoLg7g70ryNM/9k/5M3QDRazYHRKk79i9HoXGzUYzmMW8wHbpZi95AM/xe/mVglpjkStFm8xvife1ioPPCRigOTQ02M/HoqD7bKAxFlK4TKtJj+z3+SCz0GIK8fWrWaUYsCgYAScYQumy9qQY0LMIiZSrOKv2ZVksAS2d76DyxV9NW4UyfqD5uDn6JxOE2gHv58zsp/UAJ4xxMwmzDRMgNPTrnpn5iShBfGiMLElC98oMg22JIbTOK59Iv0RgPXnLGTVrUhHs4n4akqGk1N5M5/XGsdo6zpAyNb5CRX+ZpX/mIVgQKBgQCPrtESK1P12FTbrX4bkseBeQIrvqnX5SWL9+rL34f/ifAO4D5i/xOPQPZJ88RytOoH8ceN5VnqXKt2WYRx38VDwK0ecTE+5E9gOSLlwv37lJtyYHMDvuhASoqfmm9g2fI9+caosNsKDx8JzXRgLUj35Odqhx6aQlvU9oWO5GpGgQKBgQDHUl96r4UqYq6ckaw2cOJdqiMqaSSe41M+vTvaafHYN28CfnnHuFkb4gox2rkya/EK1dUOaDGk5kqruhG1NYkpC6ern2N9qA4n5jFomBqr6ru7nVAV6Td+t53trerkeNakUBTVXN9u6MMxw2zKYXwjd6dpXwS0QswivxHQYFBZRA==";
            // 私钥解密
            System.out.println("解密后的明文: " + RsaUtil.privateDecrypt(byte2Base64, privateKeyStr));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
